#ifndef CORE_CONFIG_PARSER_H_
#define CORE_CONFIG_PARSER_H_

#include <mutex>

#include "../core/global.h"
#include "../core/logger.h"

/* Parses simple configs like:

#This is a comment
foo = true
bar = 64
baz = yay

*/

class ConfigParser {
 public:
  ConfigParser(const std::string& file);
  ~ConfigParser();

  ConfigParser(const ConfigParser& other) = delete;
  ConfigParser& operator=(const ConfigParser& other) = delete;

  void warnUnusedKeys(std::ostream& out, Logger* logger) const;
  
  std::vector<std::string> unusedKeys() const;
  std::string getFileName() const;
  std::string getContents() const;

  bool contains(const std::string& key) const;

  std::string getString(const std::string& key);
  bool getBool(const std::string& key);
  int getInt(const std::string& key);
  int64_t getInt64(const std::string& key);
  uint64_t getUInt64(const std::string& key);
  float getFloat(const std::string& key);
  double getDouble(const std::string& key);

  std::string getString(const std::string& key, const std::set<std::string>& possibles);
  int getInt(const std::string& key, int min, int max);
  int64_t getInt64(const std::string& key, int64_t min, int64_t max);
  uint64_t getUInt64(const std::string& key, uint64_t min, uint64_t max);
  float getFloat(const std::string& key, float min, float max);
  double getDouble(const std::string& key, double min, double max);

  std::vector<std::string> getStrings(const std::string& key);
  std::vector<bool> getBools(const std::string& key);
  std::vector<int> getInts(const std::string& key);
  std::vector<int64_t> getInt64s(const std::string& key);
  std::vector<uint64_t> getUInt64s(const std::string& key);
  std::vector<float> getFloats(const std::string& key);
  std::vector<double> getDoubles(const std::string& key);

  std::vector<std::string> getStrings(const std::string& key, const std::set<std::string>& possibles);
  std::vector<int> getInts(const std::string& key, int min, int max);
  std::vector<int64_t> getInt64s(const std::string& key, int64_t min, int64_t max);
  std::vector<uint64_t> getUInt64s(const std::string& key, uint64_t min, uint64_t max);
  std::vector<float> getFloats(const std::string& key, float min, float max);
  std::vector<double> getDoubles(const std::string& key, double min, double max);

 private:
  std::string fileName;
  std::string contents;
  std::map<std::string, std::string> keyValues;

  mutable std::mutex usedKeysMutex;
  std::set<std::string> usedKeys;
};



#endif  // CORE_CONFIG_PARSER_H_
